﻿using System;
using System.Windows.Controls;
using NSubstitute;
using Phoenix.Frames;
using Phoenix.Framework;
using Phoenix.Lifetime;
using TestStack.BDDfy;
using TestStack.BDDfy.Scanners.StepScanners.Fluent;
using Xunit;

namespace Phoenix.Tests.Frames
{
    public class ComplexFramesScenario
    {
        NavigationFrameController navigationFrameController;
        INavigationFrameControl navigationFrame;
        INavigationFrame childNavigationFrame;
        IContentFrame childPartialView;

        [Fact]
        public void all_frames_should_be_properly_deactivated()
        {
            this.Given(s => s.GivenANavigationFrame())
                .And(s=>s.WithAChildNavigationFrame())
                .And(s=>s.AndWithAChildPartialView())
                .When(s => s.WhenParentIsDisposed())
                .Then(s=>s.ChildNavigationFrameIsDisposed())
                .And(s=>s.AndChildContentControlIsDisposed())
                .BDDfy();
        }

        [Fact]
        public void child_navigated_frame_has_child_frames_from_first_request_disposed()
        {
            this.Given(s => s.GivenANavigationFrame())
                .And(s => s.WithAChildNavigationFrame())
                .And(s => s.AndWithAChildPartialView())
                .When(s => s.WhenNavigationFrameNavigates())
                .And(s =>s.WhenParentIsDisposed())
                .Then(s => s.ChildNavigationFrameIsDisposed())
                .And(s => s.AndChildContentControlIsDisposed())
                .BDDfy();
        }

        void WhenNavigationFrameNavigates()
        {
            var controllerAction = ControllerAction.CreateFrom("Controller.Another");
            var requestTransientStore = new RequestTransientStore();
            navigationFrameController.NavigateTo(new NavigationRequest(controllerAction, null, new UserControl(), requestTransientStore, InvokeOptions.None));
        }

        void AndChildContentControlIsDisposed()
        {
            childNavigationFrame.Received().Dispose();
        }

        void ChildNavigationFrameIsDisposed()
        {
            childPartialView.Received().Dispose();
        }

        void WhenParentIsDisposed()
        {
            navigationFrameController.Dispose();
        }

        void AndWithAChildPartialView()
        {
            childPartialView = Substitute.For<IContentFrame>();
            navigationFrameController.RegisterChild(childPartialView);
        }

        void WithAChildNavigationFrame()
        {
            childNavigationFrame = Substitute.For<INavigationFrame>();
            navigationFrameController.RegisterChild(childNavigationFrame);
        }

        void GivenANavigationFrame()
        {
            navigationFrame = Substitute.For<INavigationFrameControl>();
            navigationFrameController = new NavigationFrameController(navigationFrame);
            var controllerAction = ControllerAction.CreateFrom("Controller.InitialAction");
            var currentRequest = new NavigationRequest(controllerAction, null, new UserControl(), new RequestTransientStore(), InvokeOptions.None);
            navigationFrameController.NavigateTo(currentRequest);
        }
    }
}